// Copyright 2022 a.o.smith ALL Rights Reserved
package com.liuxinlong.modules.assets.service.impl;

import com.liuxinlong.common.AosException;
import com.liuxinlong.common.ExcelData;
import com.liuxinlong.common.ExcelImportCallBack;
import com.liuxinlong.common.ExcelImportService;
import com.liuxinlong.common.ImportResp;
import com.liuxinlong.common.RowError;
import com.liuxinlong.common.SnowFlake;
import com.liuxinlong.constant.ThreadLocalConstants;
import com.liuxinlong.constant.TimeFormatConstants;
import com.liuxinlong.enums.AssetsProjectTypeEnum;
import com.liuxinlong.enums.AssetsStatusEnum;
import com.liuxinlong.enums.ReturnCodes;
import com.liuxinlong.modules.assets.dto.ImportAssetsBudgetDto;
import com.liuxinlong.modules.assets.service.AssetsBudgetService;
import com.liuxinlong.modules.dao.AssetsBudgetDao;
import com.liuxinlong.modules.dao.AssetsBudgetYearDao;
import com.liuxinlong.modules.dao.AssetsDao;
import com.liuxinlong.modules.dao.AssetsMonthDetailDao;
import com.liuxinlong.modules.dao.AssetsSettlementDao;
import com.liuxinlong.modules.dao.AssetsSourceRelationDao;
import com.liuxinlong.modules.dao.AssetsStatisticsDao;
import com.liuxinlong.modules.dao.PatentDepartmentDao;
import com.liuxinlong.modules.dao.PatentDepartmentSpecialDao;
import com.liuxinlong.modules.dao.RoleDao;
import com.liuxinlong.modules.dao.UserDao;
import com.liuxinlong.modules.dao.UserRoleRelationDao;
import com.liuxinlong.modules.entity.Assets;
import com.liuxinlong.modules.entity.AssetsBudget;
import com.liuxinlong.modules.entity.AssetsBudgetYear;
import com.liuxinlong.modules.entity.AssetsMonthDetail;
import com.liuxinlong.modules.entity.AssetsSettlement;
import com.liuxinlong.modules.entity.AssetsSourceRelation;
import com.liuxinlong.modules.entity.AssetsStatistics;
import com.liuxinlong.modules.entity.PatentDepartment;
import com.liuxinlong.modules.entity.PatentDepartmentSpecial;
import com.liuxinlong.modules.entity.User;
import com.liuxinlong.modules.entity.UserRole;
import com.liuxinlong.modules.entity.UserRoleRelation;
import com.liuxinlong.utils.ExcelUtils;
import com.liuxinlong.utils.ObjectUtils;
import com.liuxinlong.utils.ThreadlocalUtils;
import com.liuxinlong.utils.TimeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 固资预算业务接口层实现
 *
 * @author liuxinlong@hotwater.com.cn
 * @version 1.0.0
 * @since 2023-10-27
 */
@Service
@Slf4j
public class AssetsBudgetServiceImpl implements AssetsBudgetService {
    @Autowired
    private ExcelImportService excelImportService;

    @Autowired
    private AssetsBudgetDao assetsBudgetDao;

    @Autowired
    private PatentDepartmentDao patentDepartmentDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private AssetsDao assetsDao;

    @Autowired
    private AssetsSourceRelationDao assetsSourceRelationDao;

    @Autowired
    private AssetsMonthDetailDao assetsMonthDetailDao;

    @Autowired
    private AssetsBudgetYearDao assetsBudgetYearDao;

    @Autowired
    private AssetsSettlementDao assetsSettlementDao;

    @Autowired
    private AssetsStatisticsDao assetsStatisticsDao;

    @Autowired
    private RoleDao roleDao;

    @Autowired
    private UserRoleRelationDao userRoleRelationDao;

    @Autowired
    private PatentDepartmentSpecialDao patentDepartmentSpecialDao;

    @Override
    public Map<String, Object> pageAssetsBudget(Map<String, Object> queryParam) {
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        String userId = currentUser.getId();
        Map<String, Object> dataMap = new HashMap<>();
        List<UserRoleRelation> userRoleRelationList = userRoleRelationDao.queryRelationByUserId(userId);
        UserRole highRole = roleDao.getRoleBySn("J020");
        List<UserRoleRelation> existHighList;
        if (ObjectUtils.isEmpty(highRole)) {
            existHighList = new ArrayList<>();
        } else {
            existHighList = userRoleRelationList.stream().filter(relation -> StringUtils.equals(relation.getRoleId(), highRole.getId())).collect(Collectors.toList());
        }
        dataMap.put("highPermission", !existHighList.isEmpty());
        UserRole manageRole = roleDao.getRoleBySn("J021");
        List<UserRoleRelation> existList;
        if (ObjectUtils.isEmpty(manageRole)) {
            existList = new ArrayList<>();
        } else {
            existList = userRoleRelationList.stream().filter(relation -> StringUtils.equals(relation.getRoleId(), manageRole.getId())).collect(Collectors.toList());
        }
        dataMap.put("managePermission", !existList.isEmpty());
        UserRole superManageRole = roleDao.getRoleBySn("J022");
        List<UserRoleRelation> existSuperList;
        if (ObjectUtils.isEmpty(superManageRole)) {
            existSuperList = new ArrayList<>();
        } else {
            existSuperList = userRoleRelationList.stream().filter(relation -> StringUtils.equals(relation.getRoleId(), superManageRole.getId())).collect(Collectors.toList());
        }
        dataMap.put("superPermission", !existSuperList.isEmpty());
        boolean depManage = false;
        List<PatentDepartment> departmentList = patentDepartmentDao.getDepartmentByManager(userId);
        if (!ObjectUtils.isEmpty(departmentList)) {
            depManage = true;
            List<String> depList = departmentList.stream().map(PatentDepartment::getId).collect(Collectors.toList());
            queryParam.put("manageDepartment", depList);
        }
        PatentDepartmentSpecial special = patentDepartmentSpecialDao.getDepartmentSpecialById(userId);
        if (!ObjectUtils.isEmpty(special)) {
            depManage = true;
            if (queryParam.containsKey("manageDepartment")) {
                List<String> depList = (List<String>) queryParam.get("manageDepartment");
                List<String> allList = new ArrayList<>();
                allList.addAll(depList);
                allList.addAll(Arrays.asList(special.getBranch().split(",")));
                queryParam.put("manageDepartment", allList);
            } else {
                List<String> allList = Arrays.asList(special.getBranch().split(","));
                queryParam.put("manageDepartment", allList);
            }
        }
        dataMap.put("departmentPermission", !ObjectUtils.isEmpty(departmentList) || !ObjectUtils.isEmpty(special));
        if (!existHighList.isEmpty() || !existList.isEmpty() || !existSuperList.isEmpty()) {
            queryParam.put("manageDepartment", null);
//            queryParam.put("projectManage", null);
        }
        if (existHighList.isEmpty() && existList.isEmpty() && existSuperList.isEmpty() && !depManage) {
            dataMap.put("totalNum", 0);
            return dataMap;
        }
        int startNum = (int) queryParam.get("startNum");
        List<AssetsBudget> originalList = assetsBudgetDao.pageAssetsBudget(queryParam);
        List<Map<String, Object>> resultList = completeResult(originalList, startNum);
        dataMap.put("dataList", resultList);
        int totalNum = assetsBudgetDao.getAssetsBudgetCount(queryParam);
        dataMap.put("totalNum", totalNum);
        return dataMap;
    }

    @Override
    public int getAssetsBudgetCount(Map<String, Object> queryParam) {
        return assetsBudgetDao.getAssetsBudgetCount(queryParam);
    }

    @Override
    @Transactional
    public void addAssetsBudget(AssetsBudget assetsBudget, AssetsMonthDetail assetsMonthDetail) {
        AssetsBudget oldInfo = assetsBudgetDao.getAssetsBudgetByNo(assetsBudget.getPlanNo());
        if (!ObjectUtils.isEmpty(oldInfo)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "新增固资预算信息失败，固资号已存在！");
        }
        BigDecimal totalBudgetAmount = assetsMonthDetail.getJanAmount().add(assetsMonthDetail.getFebAmount()).add(assetsMonthDetail.getMarAmount()).add(
                assetsMonthDetail.getAprAmount()).add(assetsMonthDetail.getMayAmount()).add(assetsMonthDetail.getJunAmount()).add(
                assetsMonthDetail.getJulAmount()).add(assetsMonthDetail.getAugAmount()).add(assetsMonthDetail.getSepAmount()).add(
                assetsMonthDetail.getOctAmount()).add(assetsMonthDetail.getNovAmount()).add(assetsMonthDetail.getDecAmount());
        if (!totalBudgetAmount.equals(assetsBudget.getCurrentYearAmount())) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "新增固资预算信息失败，当年度花费金额存在差异！");
        }
        if (!Objects.equals(assetsBudget.getPlanAmount(), assetsBudget.getCurrentYearAmount().add(assetsBudget.getNextYearAmount()))) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "新增固资预算信息失败，计划申请金额存在差异！");
        }
        String id = SnowFlake.nextIdStr();
        assetsBudget.setId(id);
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        String userId = currentUser.getId();
        assetsBudget.setCreateUser(userId);
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        assetsBudget.setCreateTime(currentTime);
        assetsBudgetDao.insert(assetsBudget);
        String assetsId = SnowFlake.nextIdStr();
        // 构建固资信息
        Assets assets = buildAssetsInfo(assetsId, assetsBudget, userId, currentTime);
        assetsDao.insert(assets);
        // 构建固资统计信息
        AssetsStatistics statistics = buildStatistics(assets);
        assetsStatisticsDao.insert(statistics);
        // 构建固资来源信息
        AssetsSourceRelation assetsSourceRelation = buildAssetsSourceInfo(assetsId, assetsBudget, userId, currentTime);
        assetsSourceRelationDao.insert(assetsSourceRelation);
        // 构建固资月度信息
        List<AssetsMonthDetail> monthDetailList = new ArrayList<>();
        assetsMonthDetail.setId(SnowFlake.nextIdStr());
        assetsMonthDetail.setBusinessType(1);
        assetsMonthDetail.setBusinessId(id);
        assetsMonthDetail.setInfoYear(assetsBudget.getCurrentYear());
        assetsMonthDetail.setCreateTime(currentTime);
        assetsMonthDetail.setCreateUser(userId);
        monthDetailList.add(assetsMonthDetail);
        AssetsMonthDetail amdAssets = new AssetsMonthDetail();
        amdAssets.setId(SnowFlake.nextIdStr());
        amdAssets.setBusinessType(2);
        amdAssets.setBusinessId(assetsId);
        amdAssets.setInfoYear(assetsBudget.getCurrentYear());
        amdAssets.setJanAmount(assetsMonthDetail.getJanAmount());
        amdAssets.setFebAmount(assetsMonthDetail.getFebAmount());
        amdAssets.setMarAmount(assetsMonthDetail.getMarAmount());
        amdAssets.setAprAmount(assetsMonthDetail.getAprAmount());
        amdAssets.setMayAmount(assetsMonthDetail.getMayAmount());
        amdAssets.setJunAmount(assetsMonthDetail.getJunAmount());
        amdAssets.setJulAmount(assetsMonthDetail.getJulAmount());
        amdAssets.setAugAmount(assetsMonthDetail.getAugAmount());
        amdAssets.setSepAmount(assetsMonthDetail.getSepAmount());
        amdAssets.setOctAmount(assetsMonthDetail.getOctAmount());
        amdAssets.setNovAmount(assetsMonthDetail.getNovAmount());
        amdAssets.setDecAmount(assetsMonthDetail.getDecAmount());
        amdAssets.setCreateTime(currentTime);
        amdAssets.setCreateUser(userId);
        monthDetailList.add(amdAssets);
        AssetsMonthDetail forecastAssets = buildAssetsMonthInfo(assetsBudget, new ImportAssetsBudgetDto(), userId, currentTime);
        forecastAssets.setBusinessType(3);
        forecastAssets.setBusinessId(assetsId);
        monthDetailList.add(forecastAssets);
        assetsMonthDetailDao.insertBatch(monthDetailList);
    }

    @Override
    @Transactional
    public void updateAssetsBudget(AssetsBudget assetsBudget, AssetsMonthDetail assetsMonthDetail) {
        String id = assetsBudget.getId();
        if (StringUtils.isEmpty(id)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "修改固资预算信息失败，固资预算信息不存在！");
        }
        AssetsBudget oldInfo = assetsBudgetDao.selectById(id);
        if (ObjectUtils.isEmpty(oldInfo)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "修改固资预算信息失败，固资预算信息不存在！");
        }
        AssetsBudget sameNoInfo = assetsBudgetDao.getAssetsBudgetByNo(assetsBudget.getPlanNo());
        if (!ObjectUtils.isEmpty(oldInfo) && !StringUtils.equals(sameNoInfo.getId(), id)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "修改固资预算信息失败，固资号已存在！");
        }
        BigDecimal totalBudgetAmount = assetsMonthDetail.getJanAmount().add(assetsMonthDetail.getFebAmount()).add(assetsMonthDetail.getMarAmount()).add(
                assetsMonthDetail.getAprAmount()).add(assetsMonthDetail.getMayAmount()).add(assetsMonthDetail.getJunAmount()).add(
                assetsMonthDetail.getJulAmount()).add(assetsMonthDetail.getAugAmount()).add(assetsMonthDetail.getSepAmount()).add(
                assetsMonthDetail.getOctAmount()).add(assetsMonthDetail.getNovAmount()).add(assetsMonthDetail.getDecAmount());
        if (!totalBudgetAmount.equals(assetsBudget.getCurrentYearAmount())) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "修改固资预算信息失败，当年度花费金额存在差异！");
        }
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        assetsBudget.setUpdateUser(currentUser.getId());
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        assetsBudget.setUpdateTime(currentTime);
        assetsBudgetDao.updateById(assetsBudget);
        List<AssetsMonthDetail> detailList = assetsMonthDetailDao.getAssetsMonthInfo(id, assetsBudget.getCurrentYear());
        if (detailList.isEmpty()) {
            assetsMonthDetail.setId(SnowFlake.nextIdStr());
            assetsMonthDetail.setBusinessType(1);
            assetsMonthDetail.setBusinessId(id);
            assetsMonthDetail.setInfoYear(assetsBudget.getCurrentYear());
            assetsMonthDetail.setCreateTime(currentTime);
            assetsMonthDetail.setCreateUser(currentUser.getId());
            assetsMonthDetailDao.insert(assetsMonthDetail);
            return;
        }
        AssetsMonthDetail detailInfo = detailList.get(0);
        assetsMonthDetail.setId(detailInfo.getId());
        assetsMonthDetail.setBusinessId(detailInfo.getBusinessId());
        assetsMonthDetail.setBusinessType(detailInfo.getBusinessType());
        assetsMonthDetail.setCreateUser(detailInfo.getCreateUser());
        assetsMonthDetail.setCreateTime(detailInfo.getCreateTime());
        assetsMonthDetail.setUpdateUser(currentUser.getId());
        assetsMonthDetail.setUpdateTime(currentTime);
        assetsMonthDetailDao.updateById(assetsMonthDetail);
    }

    @Override
    public void deleteAssetsBudget(String id) {
//        assetsBudgetDao.deleteById(id);
    }

    @Override
    public void exportAssetsBudget(HttpServletResponse response) {
        ExcelData data = new ExcelData();
        data.setFileName("固资预算导出excel.xlsx");
        Map<String, Object> queryParam = new HashMap<>();
        queryParam.put("startNum", 0);
        queryParam.put("pageSize", 10000);
        List<AssetsBudget> assetsBudgetList = assetsBudgetDao.pageAssetsBudget(queryParam);
        Map<String, Map<String, String>> departmentMap = patentDepartmentDao.getDepartmentMap();
        Map<String, Map<String, String>> userMap = userDao.getUserMap();
        String[] head = {"展示排序", "预算号", "申请部门", "项目描述", "项目负责人", "项目类型", "计划申请金额", "计划提交时间", "当年花费", "下一年度花费", "状态"};
        data.setHead(head);
        String[][] dataList = new String[assetsBudgetList.size()][head.length];
        int index = 0;
        for (AssetsBudget assetsBudget : assetsBudgetList) {
            dataList[index][0] = String.valueOf(index + 1);
            dataList[index][1] = assetsBudget.getPlanNo();
            dataList[index][2] = departmentMap.containsKey(assetsBudget.getDepartment()) ? departmentMap.get(assetsBudget.getDepartment()).get("name") : "";
            dataList[index][3] = assetsBudget.getProjectName();
            dataList[index][4] = userMap.containsKey(assetsBudget.getProjectManage()) ? userMap.get(assetsBudget.getProjectManage()).get("name") : "";
            dataList[index][5] = String.valueOf(assetsBudget.getProjectType());
            dataList[index][6] = String.valueOf(assetsBudget.getPlanAmount());
            dataList[index][7] = assetsBudget.getPlanDate();
            dataList[index][8] = String.valueOf(assetsBudget.getCurrentYearAmount());
            dataList[index][9] = String.valueOf(assetsBudget.getNextYearAmount());
            dataList[index][10] = assetsBudget.getStatus() == 1 ? "启用" : "未启用";
            index++;
        }
        data.setData(Arrays.asList(dataList));
        ExcelUtils.exportExcel(response, data);
    }

    @Override
    public ImportResp importAssetsBudget(String fileName) {
        String filePath = fileName;
        return excelImportService.excelFile(filePath, 10, new ExcelImportCallBack() {
            @Override
            public Collection<RowError> checkRow(String[] record) {
                return checkRecordValid(record);
            }

            @Override
            public boolean persistRowToDb(String[] record) {
                AssetsBudget assetsBudget = covertToBean(record);
                return false;
//				try {
//					materialStandardDao.insert(mocDetail);
//					return true;
//				} catch (Exception e) {
//					return false;
//				}
            }

            @Override
            public ImportResp partFailure(ImportResp resp) {
                resp.setRetCode(ReturnCodes.HTTP_SUCCESS.getRetCode());
                resp.setRetMessage("导入固资预算数据部分失败，总数=" + resp.getTotal() + ",失败总数=" +
                        resp.getFailedTotal());
                return resp;
            }

            @Override
            public ImportResp allSuccess(ImportResp resp) {
                resp.setRetMessage("导入固资预算数据全部成功，总数=" + resp.getTotal());
                return resp;
            }

            @Override
            public List<Map> convertFailList(List<String[]> failRecords) {
                List<Map> list = new ArrayList<>();
                int sort = 1;
                for (String[] failRecord : failRecords) {
                    Map item = new HashMap();
                    item.put("sort", sort);
                    item.put("planDate", failRecord[0]);
                    item.put("department", failRecord[1]);
                    item.put("projectName", failRecord[5]);
                    item.put("projectManage", failRecord[7]);
                    item.put("projectType", failRecord[8]);
                    item.put("planNo", failRecord[9]);
                    item.put("planAmount", failRecord[10]);
                    item.put("planCloseDate", failRecord[15]);
                    item.put("janAmount", failRecord[16]);
                    item.put("febAmount", failRecord[17]);
                    item.put("marAmount", failRecord[18]);
                    item.put("aprAmount", failRecord[19]);
                    item.put("mayAmount", failRecord[20]);
                    item.put("junAmount", failRecord[21]);
                    item.put("julAmount", failRecord[22]);
                    item.put("augAmount", failRecord[23]);
                    item.put("sepAmount", failRecord[24]);
                    item.put("octAmount", failRecord[25]);
                    item.put("novAmount", failRecord[26]);
                    item.put("decAmount", failRecord[27]);
                    long currentYearAmount = (ObjectUtils.isEmpty(failRecord[16]) ? 0 : Long.parseLong(failRecord[16])) +
                            (ObjectUtils.isEmpty(failRecord[17]) ? 0 : Long.parseLong(failRecord[17])) +
                            (ObjectUtils.isEmpty(failRecord[18]) ? 0 : Long.parseLong(failRecord[18])) +
                            (ObjectUtils.isEmpty(failRecord[19]) ? 0 : Long.parseLong(failRecord[19])) +
                            (ObjectUtils.isEmpty(failRecord[20]) ? 0 : Long.parseLong(failRecord[20])) +
                            (ObjectUtils.isEmpty(failRecord[21]) ? 0 : Long.parseLong(failRecord[21])) +
                            (ObjectUtils.isEmpty(failRecord[22]) ? 0 : Long.parseLong(failRecord[22])) +
                            (ObjectUtils.isEmpty(failRecord[23]) ? 0 : Long.parseLong(failRecord[23])) +
                            (ObjectUtils.isEmpty(failRecord[24]) ? 0 : Long.parseLong(failRecord[24])) +
                            (ObjectUtils.isEmpty(failRecord[25]) ? 0 : Long.parseLong(failRecord[25])) +
                            (ObjectUtils.isEmpty(failRecord[26]) ? 0 : Long.parseLong(failRecord[26])) +
                            (ObjectUtils.isEmpty(failRecord[27]) ? 0 : Long.parseLong(failRecord[27]));
                    item.put("currentYearAmount", currentYearAmount);
                    item.put("nextYearAmount", Long.parseLong(failRecord[10]) - currentYearAmount);
                    item.put("plant", failRecord[31]);
                    list.add(item);
                    sort++;
                }
                return list;
            }

        });
    }

    @Override
    public ImportResp batchAddAssetsBudget(List<ImportAssetsBudgetDto> dataList) {
        Map<String, Map<String, String>> planNoMap = assetsBudgetDao.getAssetsBudgetMapByNo();
        Map<String, Map<String, String>> departmentMap = patentDepartmentDao.getDepartmentMapByName();
        Map<String, Map<String, String>> userMap = userDao.getUserMapBySn();
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        String userId = currentUser.getId();
        List<Map> failedList = new ArrayList<>();
        boolean insertSuccess;
        int sort = 1;
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        List<Assets> assetsList = new ArrayList<>();
        List<AssetsSourceRelation> relationList = new ArrayList<>();
        List<AssetsMonthDetail> monthDetailList = new ArrayList<>();
        List<AssetsStatistics> statisticsList = new ArrayList<>();
        for (ImportAssetsBudgetDto assetsBudgetDto : dataList) {
            AssetsBudget assetsBudget = new AssetsBudget();
            if (StringUtils.isNotEmpty(assetsBudgetDto.getPlanNo()) && planNoMap.containsKey(assetsBudgetDto.getPlanNo())) {
                Map item = ObjectUtils.object2Map(assetsBudgetDto);
                item.put("message", "预算号已存在！");
                item.put("sort", sort);
                failedList.add(item);
                sort++;
                continue;
            }
            assetsBudget.setPlanNo(assetsBudgetDto.getPlanNo());
            if (!departmentMap.containsKey(assetsBudgetDto.getDepartment())) {
                Map item = ObjectUtils.object2Map(assetsBudgetDto);
                item.put("message", "申请部门不存在！");
                item.put("sort", sort);
                failedList.add(item);
                sort++;
                continue;
            }
            assetsBudget.setDepartment(departmentMap.get(assetsBudgetDto.getDepartment()).get("id"));
            assetsBudget.setProjectName(assetsBudgetDto.getProjectName());
            List<String> userInfo = Arrays.asList(assetsBudgetDto.getProjectManage().split("-"));
            if (userInfo.size() != 2 || !userMap.containsKey(userInfo.get(1))) {
                Map item = ObjectUtils.object2Map(assetsBudgetDto);
                item.put("message", "项目负责人不存在！");
                item.put("sort", sort);
                failedList.add(item);
                sort++;
                continue;
            }
            assetsBudget.setProjectManage(userMap.get(userInfo.get(1)).get("id"));
            assetsBudget.setProjectType(AssetsProjectTypeEnum.getValueByName(assetsBudgetDto.getProjectType()));
            assetsBudget.setPlanAmount(assetsBudgetDto.getPlanAmount());
            assetsBudget.setLeftAmount(BigDecimal.valueOf(0));
            assetsBudget.setPlanDate(TimeUtils.formatTime(assetsBudgetDto.getPlanDate(), TimeFormatConstants.YYYYMM, TimeFormatConstants.YYYY_MM_DD_HH_MM_SS));
            assetsBudget.setPlanCloseDate(TimeUtils.formatTime(assetsBudgetDto.getPlanCloseDate(), TimeFormatConstants.YYYYMM, TimeFormatConstants.YYYY_MM_DD_HH_MM_SS));
            assetsBudget.setCurrentYearAmount(assetsBudgetDto.getCurrentYearAmount());
            assetsBudget.setNextYearAmount(assetsBudgetDto.getNextYearAmount());
            assetsBudget.setCurrentYear(assetsBudgetDto.getPlanDate().substring(0, 4));
            assetsBudget.setPlant(assetsBudgetDto.getPlant());
            assetsBudget.setStatus(StringUtils.equals(assetsBudgetDto.getStatus(), "未启用") ? 2 : 1);
            assetsBudget.setRemark(assetsBudgetDto.getRemark());
            String message = "";
            String id = SnowFlake.nextIdStr();
            assetsBudget.setId(id);
            assetsBudget.setCreateTime(currentTime);
            assetsBudget.setCreateUser(userId);
            try {
                assetsBudgetDao.insert(assetsBudget);
                insertSuccess = true;
            } catch (Exception e) {
                insertSuccess = false;
                message = e.getMessage();
            }
            if (!insertSuccess) {
                Map<String, Object> map = ObjectUtils.object2Map(assetsBudgetDto);
                map.put("sort", sort);
                map.put("message", message);
                sort++;
                failedList.add(map);
                continue;
            }
            // 固资信息
            String assetsId = SnowFlake.nextIdStr();
            Assets assets = buildAssetsInfo(assetsId, assetsBudget, userId, currentTime);
            assetsList.add(assets);
            // 固资统计信息
            AssetsStatistics statistics = buildStatistics(assets);
            statisticsList.add(statistics);
            // 固资来源信息
            AssetsSourceRelation assetsSourceRelation = buildAssetsSourceInfo(assetsId, assetsBudget, userId, currentTime);
            relationList.add(assetsSourceRelation);
            // 固资月度详情信息
            AssetsMonthDetail amdBudget = buildAssetsMonthInfo(assetsBudget, assetsBudgetDto, userId, currentTime);
            amdBudget.setBusinessType(1);
            amdBudget.setBusinessId(id);
            monthDetailList.add(amdBudget);
            AssetsMonthDetail amdAssets = buildAssetsMonthInfo(assetsBudget, assetsBudgetDto, userId, currentTime);
            amdAssets.setBusinessType(2);
            amdAssets.setBusinessId(assetsId);
            monthDetailList.add(amdAssets);
            AssetsMonthDetail forecastAssets = buildAssetsMonthInfo(assetsBudget, new ImportAssetsBudgetDto(), userId, currentTime);
            forecastAssets.setBusinessType(3);
            forecastAssets.setBusinessId(assetsId);
            monthDetailList.add(forecastAssets);
        }
        if (!assetsList.isEmpty()) {
            assetsDao.insertBatch(assetsList);
        }
        if (!statisticsList.isEmpty()) {
            assetsStatisticsDao.insertBatch(statisticsList);
        }
        if (!relationList.isEmpty()) {
            assetsSourceRelationDao.insertBatch(relationList);
        }
        if (!monthDetailList.isEmpty()) {
            assetsMonthDetailDao.insertBatch(monthDetailList);
        }
        ImportResp resp = new ImportResp();
        resp.setRetCode(failedList.size() > 0 ? ReturnCodes.HTTP_IMPORT_PART_FAIL.getRetCode() :
                ReturnCodes.HTTP_SUCCESS.getRetCode());
        resp.setFailedList(failedList);
        resp.setTotal(dataList.size());
        resp.setSuccessTotal(dataList.size() - failedList.size());
        resp.setFailedTotal(failedList.size());
        resp.setRetMessage(failedList.size() > 0 ? "导入固资预算信息部分成功" : "导入固资预算信息成功");
        return resp;
    }

    @Override
    public void updateAssetsBudgetStatus(String id) {
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        AssetsBudget assetsBudget = assetsBudgetDao.selectById(id);
        if (ObjectUtils.isEmpty(assetsBudget)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "固资预算不存在");
        }
        String currenTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        assetsBudget.setStatus(assetsBudget.getStatus() == 0 ? 1 : 0);
        assetsBudget.setUpdateUser(currentUser.getId());
        assetsBudget.setUpdateTime(currenTime);
        assetsBudgetDao.updateById(assetsBudget);
    }

    @Override
    public Map<String, Object> queryAssetsBudgetExpand(String id) {
        AssetsBudget assetsBudget = assetsBudgetDao.selectById(id);
        if (ObjectUtils.isEmpty(assetsBudget)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "固资预算不存在");
        }
        List<AssetsMonthDetail> monthDetailList = assetsMonthDetailDao.getAssetsMonthInfo(id, assetsBudget.getCurrentYear());
        if (ObjectUtils.isEmpty(monthDetailList)) {
            return new HashMap<>();
        }
        return ObjectUtils.object2Map(monthDetailList.get(0));
    }

    @Override
    public List<Map<String, Object>> pageAssetsBudgetYear(Map<String, Object> queryParam) {
        List<AssetsBudgetYear> budgetYearList = assetsBudgetYearDao.pageAssetsBudgetYear(queryParam);
        int sort = (int) queryParam.get("startNum") + 1;
        List<Map<String, Object>> dataList = new ArrayList<>(budgetYearList.size());
        for (AssetsBudgetYear assetsBudgetYear : budgetYearList) {
            Map<String, Object> item = ObjectUtils.object2Map(assetsBudgetYear);
            item.put("sort", sort);
            dataList.add(item);
            sort++;
        }
        return dataList;
    }

    @Override
    public int getAssetsBudgetYearCount(Map<String, Object> queryParam) {
        return assetsBudgetYearDao.getAssetsBudgetYearCount(queryParam);
    }

    @Override
    public void addAssetsBudgetYear(AssetsBudgetYear assetsBudgetYear) {
        AssetsBudgetYear oldInfo = assetsBudgetYearDao.getAssetsBudgetByYear(assetsBudgetYear.getCurrentYear());
        if (!ObjectUtils.isEmpty(oldInfo)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "当前年份已存在年度预算信息，请修改！");
        }
        assetsBudgetYear.setId(SnowFlake.nextIdStr());
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        assetsBudgetYear.setCreateUser(currentUser.getId());
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        assetsBudgetYear.setCreateTime(currentTime);
        assetsBudgetYearDao.insert(assetsBudgetYear);
    }

    @Override
    public void updateAssetsBudgetYear(AssetsBudgetYear assetsBudgetYear) {
        AssetsBudgetYear dbInfo = assetsBudgetYearDao.selectById(assetsBudgetYear.getId());
        if (ObjectUtils.isEmpty(dbInfo)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "年度预算信息不存在！");
        }
        AssetsBudgetYear oldInfo = assetsBudgetYearDao.getAssetsBudgetByYear(assetsBudgetYear.getCurrentYear());
        if (!ObjectUtils.isEmpty(oldInfo) && !StringUtils.equals(oldInfo.getId(), dbInfo.getId())) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "当前年份已存在年度预算信息，请修改！");
        }
        assetsBudgetYear.setCreateUser(dbInfo.getCreateUser());
        assetsBudgetYear.setCreateTime(dbInfo.getCreateTime());
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        assetsBudgetYear.setUpdateUser(currentUser.getId());
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        assetsBudgetYear.setUpdateTime(currentTime);
        assetsBudgetYearDao.updateById(assetsBudgetYear);
    }

    @Override
    public void deleteAssetsBudgetYear(String id) {
        assetsBudgetYearDao.deleteById(id);
    }

    @Override
    public List<Map<String, Object>> pageAssetsSettlement(Map<String, Object> queryParam) {
        List<AssetsSettlement> originalList = assetsSettlementDao.pageAssetsSettlement(queryParam);
        List<Map<String, Object>> dataList = new ArrayList<>(originalList.size());
        int sort = (int) queryParam.get("startNum") + 1;
        for (AssetsSettlement settlement : originalList) {
            Map<String, Object> item = ObjectUtils.object2Map(settlement);
            item.put("sort", sort);
            dataList.add(item);
            sort++;
        }
        return dataList;
    }

    @Override
    public int getAssetsSettlementCount(Map<String, Object> queryParam) {
        return assetsSettlementDao.getAssetsSettlementCount(queryParam);
    }

    @Override
    public void addAssetsSettlement(AssetsSettlement assetsSettlement) {

        AssetsSettlement dbInfo = assetsSettlementDao.getAssetsSettlementByYearMonth(assetsSettlement.getSettlementYear(), assetsSettlement.getSettlementMonth());
        if (!ObjectUtils.isEmpty(dbInfo)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "新增失败，当前月份已配置！");
        }
        List<AssetsSettlement> rangeDataList = assetsSettlementDao.getAssetsSettlementByDate(assetsSettlement.getSettlementStartDate(), assetsSettlement.getSettlementEndDate());
        if (rangeDataList.size() > 0) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "新增失败，当前时间段已配置！");
        }
        assetsSettlement.setId(SnowFlake.nextIdStr());
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        assetsSettlement.setCreateUser(currentUser.getId());
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        assetsSettlement.setCreateTime(currentTime);
        assetsSettlementDao.insert(assetsSettlement);
    }

    @Override
    public void updateAssetsSettlement(AssetsSettlement assetsSettlement) {
        AssetsSettlement dbInfo = assetsSettlementDao.getAssetsSettlementByYearMonth(assetsSettlement.getSettlementYear(), assetsSettlement.getSettlementMonth());
        if (!ObjectUtils.isEmpty(dbInfo) && !StringUtils.equals(assetsSettlement.getId(), dbInfo.getId())) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "修改失败，当前月份已配置！");
        }
        List<AssetsSettlement> rangeDataList = assetsSettlementDao.getAssetsSettlementByDate(assetsSettlement.getSettlementStartDate(), assetsSettlement.getSettlementEndDate());
        if (rangeDataList.size() > 1) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "修改失败，当前时间段已配置！");
        } else if (rangeDataList.size() == 1 && !StringUtils.equals(rangeDataList.get(0).getId(), assetsSettlement.getId())) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "修改失败，当前时间段已配置！");
        }
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        assetsSettlement.setUpdateUser(currentUser.getId());
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        assetsSettlement.setUpdateTime(currentTime);
        assetsSettlementDao.updateById(assetsSettlement);
    }

    @Override
    public void deleteAssetsSettlement(String id) {
        AssetsSettlement dbInfo = assetsSettlementDao.selectById(id);
        if (ObjectUtils.isEmpty(dbInfo)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "删除失败，结算信息不存在！");
        }
        assetsSettlementDao.deleteById(id);
    }

    /**
     * 转换数据为入库数据
     *
     * @param record 数据记录
     * @return 入库数据
     */
    private AssetsBudget covertToBean(String[] record) {
        AssetsBudget assetsBudget = new AssetsBudget();
        assetsBudget.setPlanNo(record[1].trim());
        assetsBudget.setDepartment(record[2].trim());
        assetsBudget.setProjectName(record[3].trim());
        assetsBudget.setProjectManage(record[4].trim());
        return assetsBudget;

    }

    /**
     * 校验参数合法性
     *
     * @param record 导入数据
     * @return 参数合法性
     */
    private Collection<RowError> checkRecordValid(String[] record) {
        List<RowError> rowErrors = new ArrayList<>();
        if (StringUtils.isEmpty(record[0].trim())) {
            addRowError("计划提交时间不能为空", rowErrors);
        } else {
            if (record[0].trim().length() > 20) {
                addRowError("计划提交时间长度不能超过20", rowErrors);
            }
        }
        if (StringUtils.isEmpty(record[1].trim())) {
            addRowError("申请部门不能为空", rowErrors);
        } else {
            if (record[1].trim().length() > 100) {
                addRowError("申请部门长度不能超过100", rowErrors);
            }
        }
        if (StringUtils.isEmpty(record[5].trim())) {
            addRowError("项目描述不能为空", rowErrors);
        } else {
            if (record[5].trim().length() > 100) {
                addRowError("项目描述字段非法", rowErrors);
            }
        }
        if (StringUtils.isEmpty(record[7].trim())) {
            addRowError("项目负责人不能为空", rowErrors);
        } else {

            if (record[7].trim().length() > 100) {
                addRowError("项目负责人字段非法", rowErrors);
            }
        }

        if (StringUtils.isEmpty(record[8].trim())) {
            addRowError("项目类型不能为空", rowErrors);
        } else {
            if (record[8].trim().length() > 20) {
                addRowError("项目类型长度不能超过20", rowErrors);
            }
        }
        return rowErrors;
    }

    /**
     * 添加错误行数据
     *
     * @param errorMessage 错误信息
     * @param rowErrors    错误行数据
     */
    private void addRowError(String errorMessage, List<RowError> rowErrors) {
        RowError rowError = new RowError(errorMessage);
        rowErrors.add(rowError);
    }

    /**
     * 补全数据
     *
     * @param originalList 原始数据
     * @param startNum     数据起始值
     * @return 补全数据列表
     */
    private List<Map<String, Object>> completeResult(List<AssetsBudget> originalList, int startNum) {
        Map<String, Map<String, String>> departmentMap = patentDepartmentDao.getDepartmentMap();
        Map<String, Map<String, String>> userMap = userDao.getUserMap();
        List<Map<String, Object>> resultList = new ArrayList<>();
        int sort = startNum + 1;
        for (AssetsBudget assetsBudget : originalList) {
            Map<String, Object> item = ObjectUtils.object2Map(assetsBudget);
            item.put("sort", sort);
            item.put("departmentName", departmentMap.containsKey(assetsBudget.getDepartment()) ? departmentMap.get(assetsBudget.getDepartment()).get("name") : "");
            item.put("manageName", userMap.containsKey(assetsBudget.getProjectManage()) ? userMap.get(assetsBudget.getProjectManage()).get("name") : "");
            item.put("typeName", AssetsProjectTypeEnum.getNameByValue(assetsBudget.getProjectType()));
            resultList.add(item);
            sort++;
        }
        return resultList;
    }

    /**
     * 构建固资信息
     *
     * @param assetsId     固资id
     * @param assetsBudget 固资预算信息
     * @param userId       用户id
     * @param currentTime  当前时间
     * @return 固资信息
     */
    private Assets buildAssetsInfo(String assetsId, AssetsBudget assetsBudget, String userId, String currentTime) {
        Assets assets = new Assets();
        assets.setId(assetsId);
        assets.setAssetsNo("");
        assets.setStatus(AssetsStatusEnum.PLAN.getValue());
        assets.setDepartment(assetsBudget.getDepartment());
        assets.setProjectName(assetsBudget.getProjectName());
        assets.setProjectManage(assetsBudget.getProjectManage());
        assets.setProjectType(assetsBudget.getProjectType());
        assets.setPlant(assetsBudget.getPlant());
        assets.setPlanCloseDate(assetsBudget.getPlanCloseDate());
        assets.setGreenAmount(assetsBudget.getPlanAmount());
        assets.setCurrentYear(assetsBudget.getCurrentYear());
        assets.setCurrentYearAmount(assetsBudget.getCurrentYearAmount());
        assets.setCreateUser(userId);
        assets.setCreateTime(currentTime);
        return assets;
    }

    /**
     * 构建固资来源信息
     *
     * @param assetsId     固资id
     * @param assetsBudget 固资预算信息
     * @param userId       用户id
     * @param currentTime  当前时间
     * @return 固资信息
     */
    private AssetsSourceRelation buildAssetsSourceInfo(String assetsId, AssetsBudget assetsBudget, String userId, String currentTime) {
        AssetsSourceRelation assetsSourceRelation = new AssetsSourceRelation();
        assetsSourceRelation.setId(SnowFlake.nextIdStr());
        assetsSourceRelation.setAssetsId(assetsId);
        assetsSourceRelation.setBudgetId(assetsBudget.getId());
        assetsSourceRelation.setPlanAmount(assetsBudget.getPlanAmount());
        assetsSourceRelation.setSource(1);
        assetsSourceRelation.setCreateTime(currentTime);
        assetsSourceRelation.setCreateUser(userId);
        return assetsSourceRelation;
    }

    /**
     * 构建固资预算月度信息
     *
     * @param assetsBudget    固资预算信息
     * @param assetsBudgetDto 固资预算导入信息
     * @param userId          用户id
     * @param currentTime     当前时间
     * @return 固资信息
     */
    private AssetsMonthDetail buildAssetsMonthInfo(AssetsBudget assetsBudget, ImportAssetsBudgetDto assetsBudgetDto, String userId, String currentTime) {
        AssetsMonthDetail amdBudget = new AssetsMonthDetail();
        amdBudget.setId(SnowFlake.nextIdStr());
        amdBudget.setInfoYear(assetsBudget.getCurrentYear());
        amdBudget.setJanAmount(assetsBudgetDto.getJanAmount());
        amdBudget.setFebAmount(assetsBudgetDto.getFebAmount());
        amdBudget.setMarAmount(assetsBudgetDto.getMarAmount());
        amdBudget.setAprAmount(assetsBudgetDto.getAprAmount());
        amdBudget.setMayAmount(assetsBudgetDto.getMayAmount());
        amdBudget.setJunAmount(assetsBudgetDto.getJunAmount());
        amdBudget.setJulAmount(assetsBudgetDto.getJulAmount());
        amdBudget.setAugAmount(assetsBudgetDto.getAugAmount());
        amdBudget.setSepAmount(assetsBudgetDto.getSepAmount());
        amdBudget.setOctAmount(assetsBudgetDto.getOctAmount());
        amdBudget.setNovAmount(assetsBudgetDto.getNovAmount());
        amdBudget.setDecAmount(assetsBudgetDto.getDecAmount());
        amdBudget.setCreateTime(currentTime);
        amdBudget.setCreateUser(userId);
        return amdBudget;
    }


    /**
     * 创建统计信息
     *
     * @param assets 固资信息
     * @return 固资统计信息
     */
    private AssetsStatistics buildStatistics(Assets assets) {
        AssetsStatistics assetsStatistics = new AssetsStatistics();
        assetsStatistics.setId(SnowFlake.nextIdStr());
        assetsStatistics.setAssetsId(assets.getId());
        assetsStatistics.setCurrentYear(assets.getCurrentYear());
        assetsStatistics.setCreateTime(assets.getCreateTime());
        assetsStatistics.setCreateUser(assets.getCreateUser());
        assetsStatistics.setPlanAmount(assets.getCurrentYearAmount());
        assetsStatistics.setForecastAmount(assets.getCurrentYearForecast());
        assetsStatistics.setActualAmount(assets.getCurrentYearActual());
        return assetsStatistics;
    }
}
